In this tutorial we'll learn how to build a compound widget of the Gaussian Density example.

Steps to build a compound widget:

  1. Create a class and extend it from DOMWidget or its subclasses. (If you are building a dashboard for example using HBox, VBox etc. then it makes sense to extend the class from Box, HBox or VBox as needed)
  2. Inside the class constructor call the super class constructor passing in the widgets as children
  3. Register any widget callbacks inside the constructor and define callbacks as class methods

Once the compound widget is defined in a class, it can be put in a library and used along with other interactive widgets! Compound widgets are an excellent way of building re-usable components (using just python code) which can be seamlessly integrated with ipywidgets, bqplot and other interactive widgets.


In [ ]:
import numpy as np
from scipy.stats import norm

import ipywidgets as widgets
import bqplot.pyplot as plt

In [ ]:
# extend the class from layout class VBox
class GaussianDensity(widgets.VBox):
    def __init__(self, *args, **kwargs):        
        x = np.linspace(-10, 10, 200)
        y = norm.pdf(x)

        # gaussian density figure
        self.title_tmpl = 'Gaussian Density (mu = {} and sigma = {})'
        self.pdf_fig = plt.figure(title=self.title_tmpl.format(0, 1), 
                                  layout=widgets.Layout(width='800px', height='600px'))
        self.pdf_line = plt.plot(x, y, 'm', stroke_width=3)
        
        # sliders for mu and sigma        
        self.mu_slider = widgets.FloatSlider(description='$\mu$', value=0, min=-5, max=5, step=.1)
        self.sigma_slider = widgets.FloatSlider(description='$\sigma$', value=1, min=0.1, max=5, step=.1)
        slider_layout = widgets.HBox([self.mu_slider, self.sigma_slider])
        
        # register callback with the 'value' trait of the sliders
        for slider in [self.mu_slider, self.sigma_slider]:
            slider.observe(self.update_density, 'value')
        
        # call super construction by passing in the widgets as children
        super(GaussianDensity, self).__init__(children=[self.pdf_fig, slider_layout])
    
    def update_density(self, change):
        new_mu = self.mu_slider.value
        new_sigma = self.sigma_slider.value
        # update the y attribute of the plot with the new pdf
        # computed using new mu and sigma values
        self.pdf_line.y = norm.pdf(self.pdf_line.x, new_mu, new_sigma)

        # also update the fig title
        self.pdf_fig.title = self.title_tmpl.format(new_mu, new_sigma)

In [ ]:
gaussian_density_widget = GaussianDensity()

In [ ]:
# render the compund widget like any other interactive widget
gaussian_density_widget

In [ ]:
# we can stack this compound widget together with other interactive widgets
widgets.HBox([gaussian_density_widget, widgets.IntSlider()])